﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using Coding4Fun.Phone.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using wordroid.Model;
using wordroid.Resources;
using wordroid.TTSService;
using wordroid.utils;
using Translation = wordroid.Model.Translation;

namespace wordroid.View {
    public partial class TrainingView : PhoneApplicationPage {

        public TrainingView() {

            InitializeComponent();
            _statistic = new Statistic();
            _maxWords = int.MaxValue;
            readWords();

            if (_words.Count > 0) {
                fillForm();
            }
            else {
                showMessageAndGoBack(AppResources.CaptionWordsNotExists, AppResources.TitleError);
            }
        }

        private void loadSpeaker() {
            try {
                 FrameworkDispatcher.Update();
                 var objTranslator = new TTSService.LanguageServiceClient();
                 objTranslator.GetLanguagesForSpeakAsync(Constants.APP_ID, objTranslator);
                _isSpeakerLoaded = true;
            }
            catch (Exception ex) {
                _isSpeakerLoaded = false;
                MessageBox.Show(AppResources.ErrorSpeakerCanNotBeLoaded);
            }
        }

        private void speak(Translation param) {
            LanguageServiceClient objTranslator = new LanguageServiceClient();
                objTranslator.SpeakCompleted += translator_SpeakCompleted;
                objTranslator.SpeakAsync(Constants.APP_ID, param.translation, _locale, "audio/wav", "");
        }

        private void translator_SpeakCompleted(object sender, TTSService.SpeakCompletedEventArgs e) {
            var client = new WebClient();
            client.OpenReadCompleted += ((s, args) => {
                SoundEffect se = SoundEffect.FromStream(args.Result);
                se.Play();
            });
            client.OpenReadAsync(new Uri(e.Result));
        }

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
            base.OnNavigatedTo(e);
            String wordsCountStr;

            if (NavigationContext.QueryString.TryGetValue("count", out wordsCountStr)) {

                int count;
                if (int.TryParse(wordsCountStr, out count) && count > 0) {
                        _maxWords = count;
                }
            }

            string locale;
            _locale = NavigationContext.QueryString.TryGetValue("locale", out locale) ? locale : Constants.DEFAULT_LOCALE;
            loadSpeaker();
        }

        private void readWords() {
            _words = new List<Word>(DBHelper.getInstance().Words);
            _words.Shuffle();
        }

        private void fillForm() {

            _statistic.nextWord();

            if (!_words.Any()) {
                readWords();
            }

            Word word = _words.First();
            _words.Remove(word);

            ButtonsPanel.Children.Clear();

            OriginalWordTitle.Text = word.originalWord;
            List<Translation> translations = getTranslations(word);

            foreach (Translation translation in translations) {
                AnswerPanel panel = new AnswerPanel(translation);
                panel.AnswerClick = (sender, args) => checkAnswer(panel.Trans);
                panel.SpeakerClick = (sender, args) => speak(panel.Trans);

                ButtonsPanel.Children.Add(panel);
            }
        }

        private List<Translation> getTranslations(Word word) {
            
            List<Translation> transes = DBHelper.getInstance().getTranslations(word);

            List<Translation> valid = new List<Translation>();
            List<Translation> invalid = new List<Translation>();
            
            foreach (Translation trans in transes) {
                if(trans.isValid) {
                    valid.Add(trans);
                } else {
                    invalid.Add(trans);
                }
            }

            valid.Shuffle();
            invalid.Shuffle();

            List<Translation> retValue = new List<Translation>();

            if(invalid.Count() > Constants.MAX_INV_TRANS) {
                retValue.AddRange(invalid.GetRange(0, Constants.MAX_INV_TRANS));
            } else {
                retValue.AddRange(invalid);
            }

            retValue.Add(valid.First());
            retValue.Shuffle();

            return retValue;
        }

        private void checkAnswer(Translation param) {
                        
            populateStatistic(param);

            if(param.isValid) {
                _maxWords--;
                if(_maxWords <= 0) {
                    showMessageAndGoBack(getStatisticString(), AppResources.TitleTrainingFinished);
                } else {
                    fillForm();
                }
            } else {
                new ToastPrompt {
                    FontSize = 30,
                    Message = AppResources.CaptionMistake,
                    TextOrientation = System.Windows.Controls.Orientation.Horizontal
                }.Show();
            }
        }
        
        private void showMessageAndGoBack(String caption, String title) {
            if (MessageBox.Show(caption, title, MessageBoxButton.OK) == MessageBoxResult.OK) {
                NavigationService.GoBack();
            }
        }

        private void populateStatistic(Translation param) {
            _statistic.dispatchAnswer(param);
            Scores.Text = getStatisticString();
        }

        private String getStatisticString() {
            return String.Format(AppResources.CaptionScores, _statistic.RightAnswers, _statistic.TotalAnswers,
                                        _statistic.Percentage);
        }

        private List<Word> _words;
        private readonly Statistic _statistic;
        private string _locale;
        private int _maxWords;
        private bool _isSpeakerLoaded;
    }

    internal class Statistic {
        
        public Statistic() {
            _totalAnswers = 0;
            _rightAnswers = 0;
        }

        public int TotalAnswers {
            get { return _totalAnswers; }
        }

        public int RightAnswers {
            get { return _rightAnswers; }
        }

        public int Percentage {
            get {
                if(_totalAnswers <= 0 || _rightAnswers <= 0) {
                    return 0;
                }

                return (int)Math.Floor((_rightAnswers*100)/_totalAnswers);
            }
        }

        public void nextWord() {
            _answerSetted = false;
        }

        public void dispatchAnswer(Translation answer) {
            
            if(!_answerSetted) {
                if(answer.isValid) {
                    _rightAnswers++;
                }

                _totalAnswers++;
                _answerSetted = true;
            }
        }

        private bool _answerSetted;
        private int _totalAnswers;
        private int _rightAnswers;
    }
}